package edu.cmu.cs211.exprtree.ast;

import java.math.BigDecimal;
import java.util.Map;

/**
 * A class representing an arithmatic expression, for example 2*3.14*r. Provides
 * a cfold method allowing constant folding.
 * 
 * Expression objects are immutable.
 */
public interface Expression {
	/**
	 * Executes the <a
	 * href="http://en.wikipedia.org/wiki/Constant_folding">constant folding</a>
	 * optimization. The transformations done are defined in each Expression
	 * subclass.
	 */
	public Expression cfold();

	/**
	 * @param variableAssignments -
	 *            a map containing all variables in the expression and mapping
	 *            them to a value. For example, {x=1,y=2,z=0.5}
	 * @return The resulting value after substituting the variable assignments
	 *         and reducing the expression to a single value
	 * @throws NullPointerException
	 *             if variableAssignments is null and the expression 
	 *             contains a variable
	 * @throws IllegalArgumentException
	 *             if variableAssignments does not contain a variable in the
	 *             expression
	 */
	public BigDecimal evaluate(Map<String, BigDecimal> variableAssignments);

	/**
	 * Tests the equality of two expressions. The Expressions in question must
	 * be exactly the same (same operations, same order) to be equal. For
	 * example, 1+2 and 2+1 are not equal, even though when evaluated they would
	 * be
	 */
	public boolean equals(Object obj);

	/**
	 * You haven't learned what this method does yet, however we need to
	 * implement it when we override equals.
	 */
	public int hashCode();

	/**
	 * Turns an expression into a string as defined in each subclass
	 */
	public abstract String toString();
}
